<template>
    <div v-if="!visible">
        <div class="card">
            <div class="deferred-demo-loading"></div>
        </div>
    </div>
    <slot v-else></slot>
</template>

<script>
export default {
    name: 'DeferredDemo',
    emits: ['load'],
    props: {
        options: {
            type: Object,
            default: null
        }
    },
    data() {
        return {
            visible: false
        };
    },
    observer: null,
    timeout: null,
    mounted() {
        this.observer = new IntersectionObserver(([entry]) => {
            clearTimeout(this.timeout);

            if (entry.isIntersecting) {
                this.timeout = setTimeout(() => {
                    this.visible = true;
                    this.observer.unobserve(this.$el);
                    this.$emit('load');
                }, 350);
            }
        }, this.options);

        this.observer.observe(this.$el);
    },
    beforeUnmount() {
        // `this.$el` may be `#text`, which `nodeType === 3` and `nodeName === '#text'`.
        // That is not a valid `Element`, the `unobserve` method will throw errors.
        this.$el instanceof Element && this.observer?.unobserve(this.$el);
        clearTimeout(this.timeout);
    },
    unmounted() {
        this.observer?.disconnect();
        this.observer = null;
    }
};
</script>
<style>
.deferred-demo-loading {
    border-radius: 10px;
    height: 350px;
    position: relative;
    overflow: hidden;
}

.deferred-demo-loading::after {
    content: '';
    animation: deferred-demo-loading 1.2s infinite;
    left: 0;
    position: absolute;
    right: 0;
    top: 0;
    height: 100%;
    transform: translateX(-100%);
    z-index: 1;
    border-radius: 10px;
    background: linear-gradient(90deg, rgba(255, 255, 255, 0), var(--hover-background), rgba(255, 255, 255, 0));
}

@keyframes deferred-demo-loading {
    from {
        transform: translateX(-100%);
    }
    to {
        transform: translateX(100%);
    }
}
</style>
